package com.zhanggm.hetong.hetong.utils;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.imageio.ImageIO;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.util.StringUtils;	
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPRow;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * PDF工具类 
 * @author 45466
 *
 */
public class PdfUtils {



	
	private static BaseFont DEFAULT_FONT;
	
	public static BaseFont getFont(String winPath, String linuxPath) {
		String fontPath = System.getProperty("os.name").toLowerCase().contains("windows") ? winPath : linuxPath;

		try {
			return BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("获取失败");
			return DEFAULT_FONT;
		}
	}
	
	private static BaseFont getChinseFont() throws DocumentException, IOException {
		// TODO Auto-generated method stub
		BaseFont bfChinese = BaseFont.createFont("C:/WINDOWS/Fonts/simhei.ttf", BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
		return bfChinese;
	
	}
	
	
	/**
	 * 使用步骤
	 * @param args
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 * @throws SecurityException 
	 * @throws NoSuchFieldException 
	 */
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		/*
		 * // 1. 生成文档对象 Document document = new Document(); // 不能忽略 // 获取输出对象 try {
		 * 
		 * // 生成pdf文件的的路径 PdfWriter pdfWriter = PdfUtils.createDoc(document,
		 * "d:/mytest21.pdf");//不能忽略
		 * 
		 * //添加的内容 看实际情况 List<String> list = new ArrayList<String>(); list.add("我的标题");
		 * list.add("这里是正文内容"); list.add(""); list.add("价格：" + 1234 + "     单价：" +
		 * 13.25); // 将list 中的内容添加 到PDF文件当中 PdfUtils.addContent(document, list, 18);
		 * 
		 * 
		 * // 添加一个图片 需要就加 不需要就不加
		 * PdfUtils.addImg(document,"d:/testaaaa.jpg",100,300,300,100);
		 * 
		 * // 添加一个表格 看实际情况 List<Goods> list2 = new ArrayList<Goods>(); list2.add(new
		 * Goods(1,"衣服",12344)); list2.add(new Goods(2,"袜子",213)); list2.add(new
		 * Goods(3,"腰带",321)); PdfUtils.addTable(pdfWriter,new String[]
		 * {"id","名称","价格"}, new String[] {"id","name","price"}, list2,50,200);
		 * 
		 * List<MyKeyValue> arrayList = new ArrayList<MyKeyValue>(); arrayList.add(new
		 * MyKeyValue("价格", 12+"")); arrayList.add(new MyKeyValue("mingcheng", "wazi"));
		 * 
		 * PdfUtils.addTable(pdfWriter,new String[] {"标题","内容"}, new String[]
		 * {"key","value"}, arrayList,50,100);
		 * 
		 * 
		 * document.close();// 不能忽略 pdfWriter.close();// 不能忽略
		 * 
		 * //将刚才生成的pdf 文件生成一个图片 根据实际情况 PdfUtils.pdf2png("d:/mytest21.pdf",
		 * "d:/mytest21png.png");
		 * 
		 * //将刚才生成的pdf 添加文字水印 根据实际情况 PdfUtils.markTxt(new
		 * FileInputStream("d:/mytest21.pdf"), new
		 * FileOutputStream("d:/mytest21marktext.pdf"), "=====", "beijingbawe");
		 * 
		 * //将刚才生成的pdf 添加图片水印 根据实际情况 PdfUtils.markImage("d:/dog.png", new
		 * FileInputStream("d:/mytest21marktext.pdf"), new
		 * FileOutputStream("d:/mytest21marktextimg.pdf"), "zhuzhiguang");
		 * 
		 * 
		 * } catch (Exception e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); }
		 */
	}

	
	/**
	 * 获取文档对象
	 * @throws DocumentException 
	 * @throws FileNotFoundException 
	 */
	public static PdfWriter createDoc(Document document ,String filePath) throws FileNotFoundException, DocumentException {
		
        // 2.建立一个书写器(Writer)与document对象关联，通过书写器(Writer)可以将文档写入到磁盘中。
        // 创建 PdfWriter 对象 第一个参数是对文档对象的引用，第二个参数是文件的实际名称，在该名称中还会给出其输出路径。
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filePath));
        // 3.打开文档
        document.open();
        return writer;
	}
	
	
	/**
	 * 将pdf文件转换成图片
	 * @param pdfFile
	 * @param pngFile
	 * @return
	 */
	public static boolean pdf2png(String pdfFile,String pngFile) {
		
        System.out.println("开始pdf生成png图片");
        // 将pdf装图片 并且自定义图片得格式大小
        File file = new File(pdfFile);
        try {
            PDDocument doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for (int i = 0; i < pageCount; i++) {
                BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
                // BufferedImage srcImage = resize(image, 240, 240);//产生缩略图
                ImageIO.write(image, "PNG", new File(pngFile));
                System.out.println("生成png文件：" + pngFile);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
	
	



	/**
	 *   添加水印
	 * @param is  输入流
	 * @param os  输出流
	 * @param mainMark 
	 * @param rootMark
	 * @throws DocumentException
	 * @throws IOException
	 */
    public static void markTxt(InputStream is, OutputStream os, String mainMark, String rootMark)
            throws DocumentException, IOException {
        markTxt(0.5f, 60, true, is, os, mainMark, rootMark);
    }
    
    /**
     *      加图片水印
     * @param iconPath 
     * @param is
     * @param os
     * @param rootMark
     * @throws DocumentException
     * @throws IOException
     */
    public static void markImage(String iconPath, InputStream is, OutputStream os, String rootMark)
            throws DocumentException, IOException {
        markImage(iconPath, 0.5f, 60, true, is, os, rootMark);
    }

    /**
     * 
     * @param alpha        透明度 0-1
     * @param degree    角度
     * @param isUnder    水印置于文本上/下
     * @param is        输入IO
     * @param os        输出IO
     * @param mainMark    主文本
     * @param rootMark    页脚文本
     */
    private static void markTxt(float alpha, int degree, boolean isUnder, InputStream is, OutputStream os,
            String mainMark, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        PdfStamper stamper = new PdfStamper(reader, os);

        try {
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);

            BaseFont base = getChinseFont();

            PdfContentByte content;
            int total = reader.getNumberOfPages() + 1;
            for (int i = 1; i < total; i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }
                content.setGState(gs);
                content.beginText();
                content.setColorFill(BaseColor.BLUE);
                content.setFontAndSize(base, 50);
                content.setTextMatrix(70, 200);
                content.showTextAligned(Element.ALIGN_CENTER, mainMark, 300, 350, degree);

                content.setColorFill(BaseColor.GREEN);
                content.setFontAndSize(base, 18);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();

            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }



    /**
     * 
     * @param iconPath     图标
     * @param alpha        透明度
     * @param degree    角度
     * @param isUnder    在内容下/上方加水印
     * @param is        输入IO
     * @param os        输出IO
     * @param rootMark    页脚文本描述
     */
    private static void markImage(String iconPath, float alpha, int degree, boolean isUnder, InputStream is,
            OutputStream os, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        PdfStamper stamper = new PdfStamper(reader, os);
        try {
            BaseFont base =getChinseFont();

            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);

            PdfContentByte content;
            int total = reader.getNumberOfPages() + 1;
            for (int i = 1; i < total; i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }

                content.setGState(gs);
                content.beginText();

                Image image = Image.getInstance(iconPath);
                image.setAlignment(Image.LEFT | Image.TEXTWRAP);
                image.setRotationDegrees(degree);
                image.setAbsolutePosition(200, 200);
                image.scaleToFit(200, 200);

                content.addImage(image);
                content.setColorFill(BaseColor.BLACK);
                content.setFontAndSize(base, 8);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();
            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }


	

    /**
     *       向文章中写如内容
     * @param document
     * @param list
     * @param fontName
     * @param i
     * @throws DocumentException
     * @throws IOException
     */
	public static void addContent(Document document, List<String> list, int i) throws DocumentException, IOException {
		// TODO Auto-generated method stub
		Font myFont = getFont();
		
		
		myFont.setSize(i);
		
		for (String string : list) {
			Paragraph paragraph = new Paragraph(string, myFont);
			document.add(paragraph);
		}
	}

	private static Font getFont() throws IOException, DocumentException {
		
		Font myFont;
		String fontName="";
		
		// 获取操作系统
		  String os = System.getProperty("os.name");
		 Properties properties = new Properties();
		 properties.load(PdfUtils.class.getResourceAsStream("/config.properties"));
        if(!os.toLowerCase().startsWith("win")){ // linux 操作系统
        	fontName=properties.getProperty("linuxfontpath");
        }else{
        	fontName=properties.getProperty("winfontpath");
        }
		
		if(StringUtils.hasText(fontName)) {
			BaseFont bfChinese = BaseFont.createFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
			 myFont = new Font(bfChinese);
		}else {
			BaseFont bfChinese = getChinseFont();
			 myFont = new Font(bfChinese);
		}
		return myFont;
	}


	/**
	 * 
	 * @param document  
	 * @param imgName
	 * @param x
	 * @param y
	 * @param width
	 * @param height
	 * @throws IOException 
	 * @throws MalformedURLException 
	 * @throws DocumentException 
	 */
	public static void addImg(Document document, String imgName, int x, int y, int width, int height)  {
		// TODO Auto-generated method stub

		
		// 添加图片
		Image img;
		try {
			img = Image.getInstance(imgName);
			img.setAbsolutePosition(x, y);
			img.scaleAbsolute(width, height);
			document.add(img);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.err.println("添加图片失败 " + imgName);
		}
		
	}


	/**
	 * 添加表格
	 * @param writer
	 * @param strings
	 * @param list2
	 * @throws SecurityException 
	 * @throws NoSuchFieldException 
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
	 * @throws IOException 
	 * @throws DocumentException 
	 */
	public static void addTable(PdfWriter writer, String[] titles,String[] props, List dataList,int x,int y,String winPath, String linuxPath) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, DocumentException, IOException {
		// TODO Auto-generated method stub
		PdfContentByte content = writer.getDirectContent();
		PdfPTable pTable = new PdfPTable(titles.length);
		
		BaseFont bfChinese = getFont(winPath,linuxPath);
		 Font font = new Font(bfChinese);
		 
		 
		ArrayList<PdfPRow> rows = pTable.getRows();
		//第一行是标题
		PdfPCell[] cells = new PdfPCell[titles.length];
		for (int i = 0; i < cells.length; i++) {
			cells[i]=new PdfPCell(new Paragraph(titles[i],font));
		}
		rows.add(new PdfPRow(cells));
		
		// 中间其他的数据
		for (Object data : dataList) {
			// 存储每行的数组
			PdfPCell[] cells2 = new PdfPCell[titles.length];
			
			
			  for (int i = 0; i < cells2.length; i++) {
				  // 获取data当中某个属性数值
			  
			  // 通过反射获取字段 
				Field field = data.getClass().getDeclaredField(props[i]); 
				if(field!=null  ) {
					//暴力打破封装 
					field.setAccessible(true); 
					if(field.get(data)!=null ) {
						// 设置内容
						cells2[i] = new PdfPCell(new Paragraph(field.get(data).toString(),font)); 
					}else {
						cells2[i] = new PdfPCell(new Paragraph("",font)); 
					}
				}else {
					cells2[i] = new PdfPCell(new Paragraph("",font)); 
				}
			 
			  }
			 
			rows.add(new PdfPRow(cells2));
		
			
		}
		pTable.setTotalWidth(500);
		pTable.writeSelectedRows(0, 6, x, y, content);
		
	}


	


	
}

class Goods{

   int id;
   String name;
   int price;



   public Goods() {
       super();
       // TODO Auto-generated constructor stub
   }
   public Goods(int id, String name, int price) {
       super();
       this.id = id;
       this.name = name;
       this.price = price;
   }
   public int getId() {
       return id;
   }
   public void setId(int id) {
       this.id = id;
   }
   public String getName() {
       return name;
   }
   public void setName(String name) {
       this.name = name;
   }
   public int getPrice() {
       return price;
   }
   public void setPrice(int price) {
       this.price = price;
   }

   @Override
   public String toString() {
       return "Goods [id=" + id + ", name=" + name + ", price=" + price + "]";
   }



}
 
 class MyKeyValue {
	 
	 String key;
	 String value;
	 
	public MyKeyValue() {
		super();
	}
	public MyKeyValue(String key, String value) {
		super();
		this.key = key;
		this.value = value;
	}
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	 
	 
	 
 }
